package com.onlyxiahui.aware.basic.util.string;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Description <br>
 * Date 2020-12-30 16:23:14<br>
 * 
 * @author XiaHui [onlovexiahui@qq.com]<br>
 * @since 1.0.0
 */

public class SimilarityUtil {

	public static double similarity(String source, String target) {
		double result = 0;
		if ((null == source && null == target)) {
			result = 1;
		} else if ((null == source) || (null == target) || (source.isEmpty()) || (target.isEmpty())) {
			result = 0;
		} else {
			Map<Character, int[]> vectorMap = new HashMap<Character, int[]>();
			int[] tempArray = null;
			for (Character sch : source.toCharArray()) {
				if (vectorMap.containsKey(sch)) {
					vectorMap.get(sch)[0]++;
				} else {// 用将字符转化为向量
					tempArray = new int[2];
					tempArray[0] = 1;
					tempArray[1] = 0;
					vectorMap.put(sch, tempArray);
				}
			}

			for (Character tch : target.toCharArray()) {
				if (vectorMap.containsKey(tch)) {
					vectorMap.get(tch)[1]++;
				} else {// 用将字符转化为向量
					tempArray = new int[2];
					tempArray[0] = 0;
					tempArray[1] = 1;
					vectorMap.put(tch, tempArray);
				}
			}
			result = cosine(vectorMap);
		}
		return result;
	}

	/**
	 * 
	 * 求余弦相似度 <br>
	 * Date 2020-12-30 16:41:08<br>
	 * 
	 * @param vectorMap
	 * @return
	 * @since 1.0.0
	 */
	private static double cosine(Map<Character, int[]> vectorMap) {
		double result = 0;
		result = pointMultiply(vectorMap) / squaresMultiply(vectorMap);
		return result;
	}

	/**
	 * 
	 * 求平方和 <br>
	 * Date 2020-12-30 16:41:01<br>
	 * 
	 * @param paramMap
	 * @return
	 * @since 1.0.0
	 */
	private static double squares(Map<Character, int[]> paramMap) {
		double result1 = 0;
		double result2 = 0;
		Set<Character> keySet = paramMap.keySet();
		for (Character character : keySet) {
			int temp[] = paramMap.get(character);
			result1 += (temp[0] * temp[0]);
			result2 += (temp[1] * temp[1]);
		}
		return result1 * result2;
	}

	/**
	 * 
	 * 点乘法 <br>
	 * Date 2020-12-30 16:40:52<br>
	 * 
	 * @param paramMap
	 * @return
	 * @since 1.0.0
	 */
	private static double pointMultiply(Map<Character, int[]> paramMap) {
		double result = 0;
		Set<Character> keySet = paramMap.keySet();
		for (Character character : keySet) {
			int temp[] = paramMap.get(character);
			result += (temp[0] * temp[1]);
		}
		return result;
	}

	private static double squaresMultiply(Map<Character, int[]> paramMap) {
		double result = 0;
		result = squares(paramMap);
		result = Math.sqrt(result);
		return result;
	}
}